﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Drawing.Drawing2D;
namespace THAPHANOI
{
    public partial class ThapHN : Form
    {
        /**
         * x1,y1 lần lượt là hoành độ và tung độ của cột đĩa thứ nhất
         * x2,y2 lần lượt là hoành độ và tung độ của cột đĩa thứ hai
         * x3,y3 lần lượt là hoành độ và tung độ của cột đĩa thứ ba
         */
        int x1 = 80, y1 = 430, x2 = 310, y2 = 430, x3 = 515, y3 = 430;
        // tam là biết lưu giá trị tâm của đĩa đang duy chuyển
        int inttam;

        // hoanh là biến lưu giá trị hoành độ của đĩa cao nhất khi duy chuyển đĩa lên
        int inthoanh;

        // intm là số đĩa ban đầu khi công thiếp lập hệ thống
        int intm = 3;

        // piBo là một mãng kiểu Picturebox được cấp phát trước 100 phần tử
        System.Windows.Forms.PictureBox[] piBo = new PictureBox[100];

        // random là biết lưu giá trị random để cập nhận màu cho các đĩa một cách tự động
        System.Random random = new Random();

        /**
         * Khởi động hàm timer để chuyển tiếp các tên coder
         */
        public ThapHN()
        {
            InitializeComponent();
            tmrTimer.Start(); 
        }

        /** 
         * Hàm duy chuyển đĩa từ thấp đi đến tháp đến
         */
        public void chuyen(int intdia, int intdi, ref int intthapdi, int intden, ref int intthapden) 
        {
            // Lấy hoành độ của đĩa cần duy chuyển
            inthoanh = this.piBo[intdia - 1].Location.X;
            // Lấy độ dài của đĩa cần duy chuyển
            inttam = this.piBo[intdia - 1].Size.Width;
            // Chia đôi độ dài để lấy tâm đĩa 
            inttam = inttam / 2;          
            // Kiểm tra xem intden lưu hoành độ của cột thứ mấy
            switch (intden) 
            {
                // Cột 1
                case 80: intden = intden + (75 - inttam); break;
                // Cột 2
                case 310: intden = intden + (60 - inttam); break;
                // Cột 3
                case 515: intden = intden + (65 - inttam); break; 
            }
            // Tạm dừng tiến trình để update lên màn hình form Main (1s)
            Thread.Sleep(1000);
            // Vẽ đĩa lên vị trí có hoành độ là inthoanh và tung độ là 200
            this.piBo[intdia - 1].Location = new Point(inthoanh, 200); 
            Thread.Sleep(1000);
            // Vẽ đĩa lên vị trí có hoành độ là intden và tung độ là 200
            this.piBo[intdia - 1].Location = new Point(intden, 200); 
            Thread.Sleep(1000);
            // Vẽ đia lên vị trí có hoành độ là intden và tung độ là điểm trên cùng của tháp đến
            this.piBo[intdia - 1].Location = new Point(intden, intthapden);
            // Giảm giá trị cao nhất của tháp đến 10px tương ứng với chiều cao của đĩa
            intthapden -= 10;
            // Tăng giá trị cao nhất của tháp đi 10px tương ứng với chiều cao của đĩa
            intthapdi += 10; 

        }

        /**
         * Hàm chuyển tháp
         */
        private void chuyenthap(int intdia, int intdi, int intthapdi, int intden, int intthapden, int inttam, int d_inttam)
        {

            if (intdia == 1)
            {
                this.chuyen(1, intdi, ref intthapdi, intden, ref  intthapden);
            }
            else
            {
                // Chuyển n-1 đĩa trên sang cột tạm để chuyển tầng dưới cùng đến tháp đích
                this.chuyenthap(intdia - 1, intdi, intthapdi, inttam, d_inttam, intden, intthapden);
                // Chuyển đĩa dưới cùng đến tháp đích
                this.chuyen(intdia, intdi, ref intthapdi, intden, ref intthapden);
                // Chuyển n-1 nằm trên đĩa lớn nhất ở cột đích
                this.chuyenthap(intdia - 1, inttam, d_inttam, intden, intthapden, intdi, intthapdi); 

            }

        }

        /**
         * Gán giá trị hình ảnh của background bằng hình setting
         */
        private void picSetting_MouseEnter(object sender, EventArgs e) 
        {
            picSetting.Image = THAPHANOI.Properties.Resources.setting;
        }

        /**
         * Gán giá trị hình ảnh của background bằng null
         */
        private void picSetting_MouseLeave(object sender, EventArgs e) 
        {
            picSetting.Image = null;
        }
        

        /**
         * Thoát khỏi chương trình
         */
        private void exit_Click(object sender, EventArgs e) 
        {
            this.Close();
        }

        /**
         * Tạo FormInput khởi tạo số đĩa
         */
        private void picSetting_Click(object sender, EventArgs e)
        {
            FormInput f = new FormInput(); // Khởi tạo form Input
            f.MyGetData = new FormInput.GetString(GetValue); // Khởi tạo hàm delegate
            f.Show(); // Hiện thị form Input
        }

        /**
         * Thay đổi hình ảnh khi rê chuột vào picturebox
         */
        private void butPlay_MouseEnter(object sender, EventArgs e) 
        {
            butPlay.Image = THAPHANOI.Properties.Resources.play_hover;
        }

        /**
         * Thay đổi hình ảnh lúc không rê chuột vào picturebox
         */
        private void butPlay_MouseLeave(object sender, EventArgs e) 
        {
            butPlay.Image = null;
        }

        // 
        int m;
        /**
         * Nút Play, chạy demo của chương trình
         */
        private void butPlay_Click(object sender, EventArgs e)// Hàm chạy demo
        {
            // Biến dùng để chặn chương trình demo chạy một lần
            int intdd = 0;
            if (intdd != 0)
            {
                MessageBox.Show("Chương trình chỉ chạy một lần. Vui lòng Exit để chạy lại! Thanks!");
                this.Close();
            }
            else
            {
                // Disable nút Play và Setting
                butPlay.Enabled = false;
                picSetting.Enabled = false;
                //
                if (m == 1000)
                    m = 3;

                // Vòng lặp khơi tạo số đĩa ở cột gốc
                for (int i = 1; i <= intm; i++) 
                {
                    // Cấp phát bộ nhớ
                    this.piBo[intm - i] = new PictureBox(); 
                    // Khởi tạo độ dài phụ thuộc vào thứ tự đĩa
                    this.piBo[intm - i].Size = new Size(150 - i * 20, 10);
                    // Khởi tạo vị trí phụ thuộc vào thứ tự đĩa
                    this.piBo[intm - i].Location = new Point(x1 + i * 10, y1 - (i - 1) * 10);
                    // Khởi tạo màu cho đĩa theo hàm random
                    this.piBo[intm - i].BackColor = Color.FromArgb(random.Next(254), random.Next(255), random.Next(255));
                    // Đưa đĩa vào trình quản lý
                    this.Controls.Add(piBo[intm - i]); 

                }
                // Giảm giá trị y1 tùy thuộc vào số đĩa để đĩa khi duy chuyển không bị chồng lên nhau
                y1 -= (intm - 2) * 10;
                // Khởi động timer để chuẩn bị gọi hàm chuyentham sau 1s
                sttStart.Start(); 
                intdd++;
            }
        }

        //
        int intd = 0;
        /** 
         * Hiển thị tên thành viên nhóm
         */
        private void tmrTimer_Tick(object sender, EventArgs e)
        {
            // Hiển thị tên Đinh Tiến Sỹ
            if (intd == 0)
                name.Image = THAPHANOI.Properties.Resources.sy;
            // Hiển thị tên Phan Quốc Huy
            if (intd == 1)
                name.Image = THAPHANOI.Properties.Resources.huy;
            // Hiển thị tên Nguyễn Văn Định
            if (intd == 2)
                name.Image = THAPHANOI.Properties.Resources.dinh;
            intd++;
            if (intd == 3)
                intd = 0;
        }

        private void sttStart_Tick(object sender, EventArgs e)
        {
            this.chuyenthap(intm, x1, y1, x2, y2, x3, y3); // Gọi hàm chuyển tháp
            this.sttStart.Stop(); // Dừng timer

        }

        /**
         * Khởi tạo hàm delegate
         */
        public void GetValue(int sodia) 
        {
            // Gán giá trị số đĩa từ form Input cho hàm Main ( intm )
            intm = sodia; 
        }

       
        

    }
}
